// Copyright 2021 ZUP IT SERVICOS EM TECNOLOGIA E INOVACAO SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package nancy

import (
	"fmt"
	"strconv"

	"github.com/ZupIT/horusec-devkit/pkg/enums/severities"
)

const (
	lowScoreMin                      = 0.1
	lowScoreMax                      = 3.9
	mediumScoreMin                   = 4.0
	mediumScoreMax                   = 6.9
	highScoreMin                     = 7.0
	highScoreMax                     = 8.9
	criticalScoreMin                 = 9.0
	bitSize                          = 32
	replaceDependencyText            = "pkg:golang/"
	messageVulnerabilityReferenceURL = "For more information, please checkout the following url"
)

type nancyVulnerability struct {
	Title       string `json:"Title"`
	Description string `json:"Description"`
	CvssScore   string `json:"CvssScore"`
	Reference   string `json:"Reference"`
	Cve         string `json:"Cve"`
}

func (v *nancyVulnerability) getDescription() string {
	if v.Reference == "" {
		return fmt.Sprintf("%s\n%s", v.Title, v.Description)
	}

	return fmt.Sprintf("%s\n%s %s (%s).",
		v.Title, v.Description, messageVulnerabilityReferenceURL, v.Reference)
}

func (v *nancyVulnerability) getSeverity() severities.Severity {
	score, err := strconv.ParseFloat(v.CvssScore, bitSize)
	if err != nil {
		return severities.Unknown
	}

	return v.isCriticalVulnerability(score)
}

func (v *nancyVulnerability) isCriticalVulnerability(score float64) severities.Severity {
	if score >= criticalScoreMin {
		return severities.Critical
	}

	return v.isHighVulnerability(score)
}

func (v *nancyVulnerability) isHighVulnerability(score float64) severities.Severity {
	if score >= highScoreMin && score <= highScoreMax {
		return severities.High
	}

	return v.isMediumVulnerability(score)
}

func (v *nancyVulnerability) isMediumVulnerability(score float64) severities.Severity {
	if score >= mediumScoreMin && score <= mediumScoreMax {
		return severities.Medium
	}

	return v.isLowVulnerability(score)
}

func (v *nancyVulnerability) isLowVulnerability(score float64) severities.Severity {
	if score >= lowScoreMin && score <= lowScoreMax {
		return severities.Low
	}

	return severities.Unknown
}
